﻿using System;
using System.Collections.Generic;
using LightCAD.MathLib;

namespace LightCAD.Core.Elements
{
    /// <summary>
    /// 弧长标注
    /// </summary>
    public class DimArc : LcElement
    {
        public Vector2 ArcStart;
        public Vector2 ArcEnd;
        public Vector2 ArcCenter;
        public double ArcStartAngle;
        public double ArcEndAngle;
        public double ArcMoveAngle;
        public double ArcLength;

        public Vector2 mppoint;
        public Vector2 Center;
        public double Radius;
        public double StartAngle;
        public double EndAngle;
        public double MoveAngle;
        public Vector2 Startp;
        public Vector2 Endp;
        public Vector2 dimarcMidp;

        public LcText Dimtext;
        public DimArc()
        {
            this.Type = BuiltinElementType.DimArc;
        }

        public DimArc(Vector2 arccstart, Vector2 arcend, Vector2 center, double arcstartangle, double arcendangle, double arcmoveangle, Vector2 midpoint) : this()
        {
            this.ArcStart = arccstart;
            this.ArcEnd = arcend;
            this.ArcCenter = center;
            this.mppoint = midpoint;
        }

        public void LoadDimArcProperty() {
            Center = ArcCenter;
            double arcradius = Math.Sqrt(Math.Pow(ArcCenter.X - ArcEnd.X, 2) + Math.Pow(ArcCenter.Y - ArcEnd.Y, 2));
            Radius = Math.Sqrt(Math.Pow(Center.X - mppoint.X, 2) + Math.Pow(Center.Y - mppoint.Y, 2));
            //需要移动的向量方向
            Vector2 direction = new Vector2(0, 0);
            //需要移动的距离
            double dis = Math.Abs(Radius - arcradius);
            if (Radius > arcradius)
            {
                //向外延伸
                direction = new Vector2(ArcStart.X - Center.X, ArcStart.Y - Center.Y);
                //需要移动的向量
                Vector2 movevec = (new Vector2(direction.X * dis, direction.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(direction.X, 2.0) + Math.Pow(direction.Y, 2.0))));
                Startp = ArcStart + movevec;

                //向外延伸
                direction = new Vector2(ArcEnd.X - Center.X, ArcEnd.Y - Center.Y);
                //需要移动的向量
                movevec = (new Vector2(direction.X * dis, direction.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(direction.X, 2.0) + Math.Pow(direction.Y, 2.0))));
                Endp = ArcEnd + movevec;
            }
            else {
                //向内延伸
                direction = new Vector2(Center.X - ArcStart.X, Center.Y - ArcStart.Y);
                //需要移动的向量
                Vector2 movevec = (new Vector2(direction.X * dis, direction.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(direction.X, 2.0) + Math.Pow(direction.Y, 2.0))));
                Startp = ArcStart + movevec;

                //向内延伸
                direction = new Vector2(Center.X - ArcEnd.X, Center.Y - ArcEnd.Y);
                //需要移动的向量
                movevec = (new Vector2(direction.X * dis, direction.Y * dis)) / Math.Sqrt(Math.Abs((Math.Pow(direction.X, 2.0) + Math.Pow(direction.Y, 2.0))));
                Endp = ArcEnd + movevec;
            }
            this.StartAngle = this.ArcStartAngle;
            this.EndAngle = this.ArcEndAngle;
            this.MoveAngle = this.ArcMoveAngle;
            
            var mpangle  = ThreePointGetAngle(new Vector2(this.Center.X + 100, this.Center.Y), this.Center, this.mppoint, true);
            if (StartAngle > 0)
            {
                if ((mpangle - StartAngle) > 0)
                {
                    if (MoveAngle > 0)
                    {
                        if (StartAngle + MoveAngle < mpangle)
                        {
                            MoveAngle = MoveAngle - 360;
                        }
                    }
                    else
                    {
                        if (360 + StartAngle + MoveAngle > mpangle)
                        {
                            MoveAngle = MoveAngle + 360;
                        }
                    }
                }
                else
                {
                    if (MoveAngle > 0)
                    {
                        if (StartAngle + MoveAngle - 360 < mpangle)
                        {
                            MoveAngle = MoveAngle - 360;
                        }
                    }
                    else
                    {
                        if (StartAngle + MoveAngle > mpangle)
                        {
                            MoveAngle = MoveAngle + 360;
                        }
                    }
                }
            }
            else {
                if ((mpangle - StartAngle) > 0)
                {
                    if (MoveAngle > 0)
                    {
                        if (StartAngle + MoveAngle < mpangle)
                        {
                            MoveAngle = MoveAngle - 360;
                        }
                    }
                    else
                    {
                        if (StartAngle+MoveAngle+360 > mpangle)
                        {
                            MoveAngle = MoveAngle + 360;
                        }
                    }
                }
                else {
                    if (MoveAngle > 0)
                    {
                        if (StartAngle - MoveAngle-360 < mpangle)
                        {
                            MoveAngle = MoveAngle - 360;
                        }
                    }
                    else
                    {
                        if (StartAngle + MoveAngle > mpangle)
                        {
                            MoveAngle = MoveAngle + 360;
                        }
                    }
                }
            }
            var a = Startp - Center;
            var b = Endp - Center;
            var m = a + b;
            m.Normalize();
            m = m * Radius;
            this.dimarcMidp = Center + m;
            if (Math.Abs(this.MoveAngle) > 180)
            {
                this.dimarcMidp = Vector2.Rotate(this.dimarcMidp, this.Center, 180);
            }

        }

        /// <summary>
        /// 三点确定角度
        /// </summary>
        /// <param name="startpoint"></param>
        /// <param name="centerpoint"></param>
        /// <param name="endpoint"></param>
        /// <param name="reversal">是否开启顺时针180为正，逆时针180为负,默认为逆时针负角度</param>
        /// <returns></returns>
        public double ThreePointGetAngle(Vector2 startpoint, Vector2 centerpoint, Vector2 endpoint, bool reversal = false)
        {
            double angle = 0;
            var so = new Vector2(startpoint.X - centerpoint.X, startpoint.Y - centerpoint.Y);
            var eo = new Vector2(endpoint.X - centerpoint.X, endpoint.Y - centerpoint.Y);
            var pddir = (so.X * eo.Y) - (so.Y * eo.X);
            angle = (so.Angle() - eo.Angle()) / Math.PI * 180;
            if (reversal)
            {
                angle = (so.Angle() + (pddir < 0 ? (2 * Math.PI - eo.Angle()) : -eo.Angle())) / Math.PI * 180;
            }

            return angle;
        }

        public override Box2 GetBoundingBox()
        {
            return new Box2().SetFromPoints(this.Startp, this.Endp);
        }
        public override Box2 GetBoundingBox(Matrix3 matrix)
        {
            return new Box2().SetFromPoints(matrix.MultiplyPoint(this.Startp), matrix.MultiplyPoint(this.Endp));
        }
        public override bool IntersectWithBox(Polygon2d testPoly, List<RefChildElement> intersectChildren = null)
        {
            var thisBox = this.BoundingBox;
            if (!thisBox.IntersectsBox(testPoly.BoundingBox))
            {
                //如果元素盒子，与多边形盒子不相交，那就可能不相交
                return false;
            }
            return GeoUtils.IsPolygonIntersectLine(testPoly.Points, this.Startp, this.Endp)
                || GeoUtils.IsPolygonContainsLine(testPoly.Points, this.Startp, this.Endp);
        }

        public override bool IncludedByBox(Polygon2d testPoly, List<RefChildElement> includedChildren = null)
        {
            var thisBox = this.BoundingBox;
            if (!thisBox.IntersectsBox(testPoly.BoundingBox))
            {
                return false;
            }
            return GeoUtils.IsPolygonContainsLine(testPoly.Points, this.Startp, this.Endp);
        }
        public override LcElement Clone()
        {
            var clone = new DimArc();
            clone.Copy(this);
            return clone;
        }

        public override void Copy(LcElement src)
        {
            var dim = ((DimArc)src);
        }

        public void Set(Vector2 start = null, Vector2 end = null, bool fireChangedEvent = true)
        {
            
        }
    }
}
